package com.wjk.easy.ui;

import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.LinearSmoothScroller;
import androidx.recyclerview.widget.RecyclerView;

import com.wjk.easy.R;
import com.wjk.easy.adapter.ExamDataAdapter;
import com.wjk.easy.adapter.ExamGroupAdapter;
import com.wjk.easy.adapter.ExamListAdapter;
import com.wjk.easy.blue.FastBleService;
import com.wjk.easy.blue.PinBlueReceiver;
import com.wjk.easy.blue.rd915demo.BTClient;
import com.wjk.easy.blue.rd915demo.UhfService;
import com.wjk.easy.uhf.EPCReadListener;
import com.wjk.easy.uhf.UHFController;
import com.wjk.easy.db.Exam;
import com.wjk.easy.db.ExamData;
import com.wjk.easy.db.LastUserBean;
import com.wjk.easy.utils.D;
import com.wjk.easy.utils.UHFUtil;
import com.wjk.easy.view.CreateExamDataDialog;
import com.wjk.easy.view.RecycleViewDivider;
import com.wjk.easy.view.TopSmoothScroller;

import org.litepal.crud.callback.SaveCallback;
import org.litepal.crud.callback.UpdateOrDeleteCallback;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;


public class ExamActivity extends AppCompatActivity implements EPCReadListener {


    private LastUserBean currentUser;

    private final int MSG_EPC_GOT = 1;
    private static final int MSG_UHF_LOAD_OK =2;
    private static final int MSG_DATA_SAVE_OK =3;
    private static final int MSG_DATA_SAVE_FAIL =4;
    private static final int MSG_UPDATE_READING =5;

    private List<String> scanResult = new ArrayList<>();
    static Map<String, byte[]> epcBytes = new HashMap<String, byte[]>();
    //private boolean stopReadBle;
    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case MSG_EPC_GOT:
                    if (dialog != null && dialog.isShowing()) {
                        dialog.setCardId((String) msg.obj);
                    } else {
                        showAddDialog((String) msg.obj);
                        findExamAndGroupByCardId((String) msg.obj);
                    }
                    break;
                case MSG_UHF_LOAD_OK:
                    uhfController.setUHFListener(ExamActivity.this);
                    Toast.makeText(ExamActivity.this, "设备已就绪", Toast.LENGTH_SHORT).show();
                    break;
                case MSG_DATA_SAVE_OK:
                    Toast.makeText(ExamActivity.this, "操作成功", Toast.LENGTH_SHORT).show();
                    loadExamData();
                    break;
                case MSG_DATA_SAVE_FAIL:
                    Toast.makeText(ExamActivity.this, "操作失败", Toast.LENGTH_SHORT).show();
                    break;
                case 33:
                    Toast.makeText(ExamActivity.this, (CharSequence) msg.obj, Toast.LENGTH_SHORT).show();
                    break;
                case 34:
                    /*: readData:S T  :-    1.32g  */
                    String weightMsg = (String) msg.obj;
                    if(weightMsg.length()>1){
                        if(weightMsg.contains("\n")){
                            weightMsg = weightMsg.split("\n")[0];
                        }
                        String s = weightMsg.replaceAll("[^0-9.]","");;
                        s = s.trim();
                        dialog.setWeight(s);
                    }
                    break;
                case MSG_UPDATE_READING:
                    if (scanResult.size()>0) {
                        onBleEpcGot();
                    }
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    };

    private boolean bleEpcGotRunning;
    private void onBleEpcGot(){
        if(!bleEpcGotRunning){
            stopSearchCard();
            canReadWeight = true;
            UHFUtil.play(1, 0);
            String epcStr = scanResult.get(0);
            Log.d("wjk","on epc get: "+epcStr);
            if (dialog != null && dialog.isShowing()) {
                dialog.setCardId(epcStr);
            } else {
                showAddDialog(epcStr);
                findExamAndGroupByCardId(epcStr);
            }
            bleEpcGotRunning=true;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
                        bleEpcGotRunning=false;
                    }
                }
            }).start();
        }
    }
    /**
     * 如果之前的实验中已经录入过该卡号，则自动跳转到对应的实验和分组
     * @param cardId 卡号
     */
    private void findExamAndGroupByCardId(String cardId) {
        ExamData examData = D.queryIfCardExist(cardId, currentUser.getUserId());
        if(examData!=null) {
            if(examData.getExamId()==currExamId&&currGroupId==examData.getGroupId()){
                return;
            }
            if(examData.getExamId()!=currExamId){
                currExamId = examData.getExamId();
                ExamListAdapter adapter = (ExamListAdapter) mExamListView.getAdapter();
                adapter.switchItem(currExamId);
                loadExamData();
            }
            if(currGroupId!=examData.getGroupId()){
                currGroupId=examData.getGroupId();
                ExamListAdapter adapter = (ExamListAdapter) mExamListView.getAdapter();
                Exam item = adapter.getItem(currExamId);
                loadGroupData(item.getGroups());
                loadExamData();
            }
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_exam);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();//返回
            }
        });

        ViewGroup fab = findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showAddDialog("");
            }
        });

        initView();
        initData();
    }

    RecyclerView mDataListView, mExamListView, mGroupListView;
    TextView noDataTip;
    ViewGroup container;
    ExamDataAdapter mDataAdapter;

    private void initView() {
        mDataListView = findViewById(R.id.rv_list_data);
        mExamListView = findViewById(R.id.rv_list_exam);
        mGroupListView = findViewById(R.id.rv_list_group);

        noDataTip = findViewById(R.id.tv_no_exam_tip);
        container = findViewById(R.id.container);

        LinearLayoutManager groupManager = new LinearLayoutManager(this);
        LinearLayoutManager examManager = new LinearLayoutManager(this);
        LinearLayoutManager dataManager = new LinearLayoutManager(this);
        groupManager.setOrientation(RecyclerView.HORIZONTAL);//设置滚动方向，横向滚动
        mDataListView.setLayoutManager(dataManager);
        mDataListView.addItemDecoration(new RecycleViewDivider(
                this, LinearLayoutManager.VERTICAL, 1, getResources().getColor(R.color.colorDarkTrans)));
        mExamListView.setLayoutManager(examManager);
        mGroupListView.setLayoutManager(groupManager);

        noDataTip.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startActivityForResult(new Intent(ExamActivity.this, ExamManageActivity.class), 1);
            }
        });

    }

    private UHFController uhfController;

    private void initData() {
        currentUser = D.queryCurrentUser(this);
        if (currentUser != null) {
            List<Exam> examList = D.queryExamList(currentUser.getUserId());
            if (examList.size() < 1) {
                showNoExam();
            } else {
                initAdapters(examList);
                showHaveExam();
                //initUhf();
                initBlueUhf();
                initBlueSSP();
            }
        }
    }
    Thread readWeightThread;
    boolean canReadWeight;
    private void initBlueSSP() {
        if(PinBlueReceiver.bluetoothSocket==null){
            Log.e("wjk","blue socket is null");
        }else{
            readWeightThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    //mHandler.sendEmptyMessage(20);
                    while (true) {
                        if(canReadWeight){
                            InputStream in;
                            try {
                                in = PinBlueReceiver.bluetoothSocket.getInputStream();
                                byte[] readData = new byte[1024];
                                if (in == null) {
                                    return;
                                }
                                int size = in.read(readData);
                                if (size > 0) {
                                    String strData = new String(readData, 0, size);
                                    Message message = mHandler.obtainMessage(34);
                                    message.obj=strData;
                                    mHandler.sendMessage(message);
                                    //Log.d("wjk","readData:"+new String(readData, 0, size));
                                }
                            } catch (IOException e) {
                                Log.d("wjk","readData exception"+e.toString());
                                e.printStackTrace();
                            }
                            try {
                                Thread.sleep(800);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            });
            readWeightThread.start();
        }
    }

    Timer readUhfTimer;
    private void initBlueUhf() {
        UHFUtil.initSoundPool(this);
        startSearchCard();
    }

    private void startSearchCard() {
        readUhfTimer = new Timer();
        readUhfTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                String[] label = BTClient.ScanUID();
                if (label == null) {
                    return;
                }
                scanResult.clear();
                for (String epcStr : label) {
                    if (epcStr == null || epcStr.equals(""))
                        break;
                    scanResult.add(epcStr);
                }
                mHandler.removeMessages(MSG_UPDATE_READING);
                mHandler.sendEmptyMessage(MSG_UPDATE_READING);
            }
        }, 0, 20);
    }

    private void stopSearchCard(){
        if(readUhfTimer!=null){
            readUhfTimer.cancel();
            try {
                readUhfTimer.purge();
            } catch (Exception e) {
                e.printStackTrace();
                readUhfTimer=null;
            }
        }
    }

    private void initUhf() {
        uhfController = new UHFController(this);
        uhfController.initUhf(new UHFController.UHFLoadListener() {
            @Override
            public void onLoadOk() {
                Message message = mHandler.obtainMessage(MSG_UHF_LOAD_OK);
                mHandler.sendMessage(message);
            }
        });
    }

    ExamGroupAdapter groupAdapter;

    private void initAdapters(List<Exam> examList) {
        ExamListAdapter mAdapter = new ExamListAdapter(this, examList);
        mAdapter.setExamChangeListener(new ExamListAdapter.OnExamChangeListener() {
            @Override
            public void onExamChange(Exam exam) {
                //TODO 实验切换
                if (currExamId != exam.getId()) {
                    currExamId = exam.getId();
                    currGroupId = 1;
                    loadExamData();
                    loadGroupData(exam.getGroups());
                }
            }
        });
        mExamListView.setAdapter(mAdapter);
        Exam defaultExam = examList.get(0);
        groupAdapter = new ExamGroupAdapter(this, defaultExam.getGroups());
        groupAdapter.setGroupChangeListener(new ExamGroupAdapter.GroupChangeLister() {
            @Override
            public void onGroupChange(int groupId) {
                //TODO 分组切换
                currGroupId = groupId;
                loadExamData();
            }
        });
        mGroupListView.setAdapter(groupAdapter);
        currExamId = defaultExam.getId();
        currGroupId = 1;
        loadExamData();
    }

    private void loadGroupData(int groups) {
        if (groupAdapter != null) {
            groupAdapter.setGroupNum(groups, currGroupId);
            int position = currGroupId-1;
            //Toast.makeText(this, "滑到：" + position, Toast.LENGTH_SHORT).show();
            LinearSmoothScroller s1 = new TopSmoothScroller(this);
            s1.setTargetPosition(position);
            mGroupListView.getLayoutManager().startSmoothScroll(s1);
        }
    }


    int currExamId, currGroupId;

    /**
     * 根据当前实验ID和分组ID查询并加载实验数据列表
     */
    private void loadExamData() {
        //默认查询第一个实验中第一个分组的实验数据
        List<ExamData> examDataList = D.queryExamDataList(currentUser.getUserId(), currExamId, currGroupId);
        if (examDataList.size() > 0) {
            if (mDataAdapter == null) {
                mDataAdapter = new ExamDataAdapter(this, examDataList);
                mDataAdapter.setEmptyListener(new ExamDataAdapter.EmptyListener() {
                    @Override
                    public void onEmpty() {
                        showNoExamData();
                    }
                });
                mDataListView.setAdapter(mDataAdapter);
            } else {
                mDataAdapter.setDataList(examDataList);
            }
            showHaveExamData();
        } else {
            showNoExamData();
        }
    }


    private void showNoExamData() {
        findViewById(R.id.tv_no_data_tip).setVisibility(View.VISIBLE);
        mDataListView.setVisibility(View.GONE);
    }

    private void showHaveExamData() {
        findViewById(R.id.tv_no_data_tip).setVisibility(View.GONE);
        mDataListView.setVisibility(View.VISIBLE);
    }

    private void showNoExam() {
        container.setVisibility(View.GONE);
        findViewById(R.id.fab).setVisibility(View.GONE);
        noDataTip.setVisibility(View.VISIBLE);
    }

    private void showHaveExam() {
        container.setVisibility(View.VISIBLE);
        findViewById(R.id.fab).setVisibility(View.VISIBLE);
        noDataTip.setVisibility(View.GONE);
    }

    private CreateExamDataDialog dialog;

    private void showAddDialog(String epc) {
        dialog = new CreateExamDataDialog(this, R.style.Theme_AppCompat_Light_Dialog_Alert, new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                final ExamData data = (ExamData) view.getTag();
                data.setUserId(currentUser.getUserId());
                final ExamData examDataExistToday = D.queryIfExamDataExistToday(data.getCardId(), currentUser.getUserId());
                if(examDataExistToday!=null){
                    //当天存在历史数据
                    new AlertDialog.Builder(ExamActivity.this)
                            .setTitle("该记录已存在（当天）")
                            .setMessage("确定要覆盖吗？")
                            .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    D.updateData(examDataExistToday.getId(), data, new UpdateOrDeleteCallback() {
                                        @Override
                                        public void onFinish(int rowsAffected) {
                                            Message msg = mHandler.obtainMessage();
                                            if (rowsAffected>0) {
                                                msg.what=MSG_DATA_SAVE_OK;
                                            } else {
                                                msg.what= MSG_DATA_SAVE_FAIL;
                                            }
                                            mHandler.sendMessage(msg);
                                        }
                                    });
                                    dialog.dismiss();
                                }
                            })
                            .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    dialog.dismiss();
                                }
                            }).show();
                }else{
                    D.saveData(data, new SaveCallback() {
                        @Override
                        public void onFinish(boolean success) {
                            Log.i("wjk", success + "");
                            Message msg = mHandler.obtainMessage();
                            if (success) {
                                msg.what=MSG_DATA_SAVE_OK;
                            } else {
                                msg.what= MSG_DATA_SAVE_FAIL;
                            }
                            mHandler.sendMessage(msg);
                        }
                    });
                }
                if (uhfController != null) uhfController.restart();
            }
        });
        dialog.setExam(currExamId, currGroupId);
        if (!epc.isEmpty()) {
            dialog.setCardId(epc);
        }
        dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
            @Override
            public void onDismiss(DialogInterface dialogInterface) {
                if (uhfController != null) uhfController.restart();
                //stopReadBle = false;
                startSearchCard();
                canReadWeight = false;
            }
        });
        dialog.show();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        if (requestCode == 1 && resultCode == 200) {
            initData();
        } else {
            super.onActivityResult(requestCode, resultCode, data);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (dialog == null || !dialog.isShowing()) {
            if(uhfController!=null)
                uhfController.onPause();
        }
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        if(uhfController!=null){
            uhfController.restart();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(uhfController!=null)
        uhfController.onDestroy();
        if(readUhfTimer!=null){
            readUhfTimer.cancel();
            readUhfTimer = null;
        }
        if(readWeightThread!=null){
            readWeightThread.interrupt();
            readWeightThread = null;
        }
    }

    @Override
    public void onEpcGot(String epcStr) {
        if (mHandler != null) {
            Message message = mHandler.obtainMessage(MSG_EPC_GOT);
            message.obj = epcStr;
            mHandler.sendMessage(message);
        }
    }


    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if(event.getKeyCode()==KeyEvent.KEYCODE_BACK){
            return super.dispatchKeyEvent(event);
        }
        return true;
    }
}
